From ebbb729aeacf4d9369d89a4b290eef6f60b53c85 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Fri, 24 Jul 2020 20:45:22 +0200 Subject: [PATCH] gl renderer: Linear gradient state tracking --- gsk/gl/gskglrenderer.c | 31 +++++++++-------- gsk/gl/gskglrenderops.c | 63 ++++++++++++++++++++++++++++++++++ gsk/gl/gskglrenderopsprivate.h | 15 ++++++++ gsk/gl/opbuffer.h | 10 +++--- 4 files changed, 101 insertions(+), 18 deletions(-) diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 7346912eef..e2e5d85320 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -1129,16 +1129,15 @@ render_linear_gradient_node (GskGLRenderer *self, const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node, NULL); const graphene_point_t *start = gsk_linear_gradient_node_peek_start (node); const graphene_point_t *end = gsk_linear_gradient_node_peek_end (node); - OpLinearGradient *op; ops_set_program (builder, &self->programs->linear_gradient_program); - op = ops_begin (builder, OP_CHANGE_LINEAR_GRADIENT); - op->color_stops = stops; - op->n_color_stops = n_color_stops; - op->start_point.x = start->x + builder->dx; - op->start_point.y = start->y + builder->dy; - op->end_point.x = end->x + builder->dx; - op->end_point.y = end->y + builder->dy; + ops_set_linear_gradient (builder, + n_color_stops, + stops, + builder->dx + start->x, + builder->dy + start->y, + builder->dx + end->x, + builder->dy + end->y); load_vertex_data (ops_draw (builder, NULL), node, builder); } @@ -2687,12 +2686,16 @@ apply_linear_gradient_op (const Program *program, const OpLinearGradient *op) { OP_PRINT (" -> Linear gradient"); - glUniform1i (program->linear_gradient.num_color_stops_location, op->n_color_stops); - glUniform1fv (program->linear_gradient.color_stops_location, - op->n_color_stops * 5, - (float *)op->color_stops); - glUniform2f (program->linear_gradient.start_point_location, op->start_point.x, op->start_point.y); - glUniform2f (program->linear_gradient.end_point_location, op->end_point.x, op->end_point.y); + if (op->n_color_stops.send) + glUniform1i (program->linear_gradient.num_color_stops_location, op->n_color_stops.value); + + if (op->color_stops.send) + glUniform1fv (program->linear_gradient.color_stops_location, + op->n_color_stops.value * 5, + (float *)op->color_stops.value); + + glUniform2f (program->linear_gradient.start_point_location, op->start_point[0], op->start_point[1]); + glUniform2f (program->linear_gradient.end_point_location, op->end_point[0], op->end_point[1]); } static inline void diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c index 0ce0e2c2c0..11269eec88 100644 --- a/gsk/gl/gskglrenderops.c +++ b/gsk/gl/gskglrenderops.c @@ -889,3 +889,66 @@ ops_set_unblurred_outset_shadow (RenderOpBuilder *self, else op->offset.send = FALSE; } + +void +ops_set_linear_gradient (RenderOpBuilder *self, + guint n_color_stops, + const GskColorStop *color_stops, + float start_x, + float start_y, + float end_x, + float end_y) +{ + ProgramState *current_program_state = get_current_program_state (self); + OpLinearGradient *op; + const guint real_n_color_stops = MIN (MAX_GRADIENT_STOPS, n_color_stops); + + g_assert (current_program_state); + + op = ops_begin (self, OP_CHANGE_LINEAR_GRADIENT); + + /* We always save the n_color_stops value in the op so the renderer can use it in + * cases where we send the color stops, but not n_color_stops */ + op->n_color_stops.value = real_n_color_stops; + if (current_program_state->linear_gradient.n_color_stops != real_n_color_stops) + { + op->n_color_stops.send = TRUE; + current_program_state->linear_gradient.n_color_stops = real_n_color_stops; + } + else + op->n_color_stops.send = FALSE; + + op->color_stops.send = FALSE; + if (!op->n_color_stops.send) + { + g_assert (current_program_state->linear_gradient.n_color_stops == real_n_color_stops); + + for (guint i = 0; i < real_n_color_stops; i ++) + { + const GskColorStop *s1 = &color_stops[i]; + const GskColorStop *s2 = ¤t_program_state->linear_gradient.color_stops[i]; + + if (s1->offset != s2->offset || + !gdk_rgba_equal (&s1->color, &s2->color)) + { + op->color_stops.send = TRUE; + break; + } + } + } + else + op->color_stops.send = TRUE; + + if (op->color_stops.send) + { + op->color_stops.value = color_stops; + memcpy (¤t_program_state->linear_gradient.color_stops, + color_stops, + sizeof (GskColorStop) * real_n_color_stops); + } + + op->start_point[0] = start_x; + op->start_point[1] = start_y; + op->end_point[0] = end_x; + op->end_point[1] = end_y; +} diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index de8b30ddd9..ebb39e355a 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -14,6 +14,7 @@ #define GL_N_VERTICES 6 #define GL_N_PROGRAMS 13 +#define MAX_GRADIENT_STOPS 8 typedef struct { @@ -136,6 +137,12 @@ typedef struct float spread; GdkRGBA color; } unblurred_outset_shadow; + struct { + int n_color_stops; + GskColorStop color_stops[MAX_GRADIENT_STOPS]; + float start_point[2]; + float end_point[2]; + } linear_gradient; }; } ProgramState; @@ -264,6 +271,14 @@ void ops_set_unblurred_outset_shadow (RenderOpBuilder *se float dx, float dy); +void ops_set_linear_gradient (RenderOpBuilder *self, + guint n_color_stops, + const GskColorStop *color_stops, + float start_x, + float start_y, + float end_x, + float end_y); + GskQuadVertex * ops_draw (RenderOpBuilder *builder, const GskQuadVertex vertex_data[GL_N_VERTICES]); diff --git a/gsk/gl/opbuffer.h b/gsk/gl/opbuffer.h index 8637d79657..9604f4b852 100644 --- a/gsk/gl/opbuffer.h +++ b/gsk/gl/opbuffer.h @@ -42,11 +42,13 @@ typedef enum } OpKind; +typedef struct { int value; guint send: 1; } IntUniformValue; typedef struct { float value; guint send: 1; } FloatUniformValue; typedef struct { float value[2]; guint send: 1; } Float2UniformValue; typedef struct { GskRoundedRect value; guint send: 1; guint send_corners: 1; } RRUniformValue; typedef struct { const GdkRGBA *value; guint send: 1; } RGBAUniformValue; typedef struct { const graphene_vec4_t *value; guint send: 1; } Vec4UniformValue; +typedef struct { const GskColorStop *value; guint send: 1; } ColorStopUniformValue; /* OpNode are allocated within OpBuffer.pos, but we keep * a secondary index into the locations of that buffer @@ -129,10 +131,10 @@ typedef struct typedef struct { - const GskColorStop *color_stops; - graphene_point_t start_point; - graphene_point_t end_point; - int n_color_stops; + ColorStopUniformValue color_stops; + IntUniformValue n_color_stops; + float start_point[2]; + float end_point[2]; } OpLinearGradient; typedef struct -- 2.30.2